package org.kzwl.comm.utils;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.aliyuncvc.model.v20191030.*;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.aliyuncvc.model.v20191030.GetUserResponse.UserInfo;
import com.aliyuncs.profile.IClientProfile;
import org.kzwl.comm.advice.BizException;
import org.kzwl.comm.advice.Consts;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import java.util.ArrayList;
import java.util.List;

public class AliUtils {
    public static void main(String[] args) {
        String uri = "rtmp://tuiliu.kongzhongwangluo.top/zzz/ccc";  // original uri
        String key = "JPXQB1eXpn";                       // private key of authorization
        long exp = System.currentTimeMillis() / 1000 + 1 * 3600;  // expiration time: 1 hour after current time
        Map<String, String> map = aAuth(uri, key, exp,"ccc");// auth type:
        System.out.println("推流" + JSONObject.toJSONString(map));

        uri = "rtmp://zhibo.kongzhongwangluo.top/zzz/ccc";  // original uri
        key = "9vZzoLPvQE";                       // private key of authorization
        exp = System.currentTimeMillis() / 1000 + 1 * 3600;  // expiration time: 1 hour after current time
        map = aAuth(uri, key, exp,"ccc");                    // auth type:
        System.out.println("播流" + JSONObject.toJSONString(map));
    }

    //生成鉴权串
    public static Map<String, String> aAuth(String uri, String key, long exp,String streamName) {
        String pattern = "^(rtmp://)?([^/?]+)(/[^?]*)?(\\\\?.*)?$";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(uri);
        String scheme = "", host = "", path = "", args = "";
        if (m.find()) {
            scheme = m.group(1) == null ? "rtmp://" : m.group(1);
            host = m.group(2) == null ? "" : m.group(2);
            path = m.group(3) == null ? "/" : m.group(3);
            args = m.group(4) == null ? "" : m.group(4);
        } else {
            System.out.println("NO MATCH");
        }

        String rand = "0";  // "0" by default, other value is ok
        String uid = "0";   // "0" by default, other value is ok
        String sString = String.format("%s-%s-%s-%s-%s", path, exp, rand, uid, key);
        String hashValue = md5Sum(sString);
        String authKey = String.format("%s-%s-%s-%s", exp, rand, uid, hashValue);
        //推流 : rtmp://tuiliu.kongzhongwangluo.top/zzz/ccc
        //Auth: rtmp://tuiliu.kongzhongwangluo.top/zzz/ccc?auth_key=1610100863-0-0-8ed4378e656b234754920005fceafb56
        //播流 : rtmp://zhibo.kongzhongwangluo.top/zzz/ccc
        //Auth: rtmp://zhibo.kongzhongwangluo.top/zzz/ccc?auth_key=1610100863-0-0-589a075480bfa62b90fc63e418aeb8ae
        Map<String, String> map = new HashMap<>();
        if (args.isEmpty()) {
            map.put("url", String.format("%s%s%s%s", scheme, host, path, args));
            map.put("streamName", String.format("%s?auth_key=%s",  streamName,authKey));
            map.put("auth", String.format("%s%s%s%s?auth_key=%s", scheme, host, path, args, authKey));
//            return String.format("%s%s%s%s?auth_key=%s", scheme, host, path, args, authKey);
        } else {
            map.put("url", String.format("%s", scheme));
            map.put("streamName", String.format("%s&auth_key=%s", streamName, authKey));
            map.put("auth", String.format("%s%s%s%s&auth_key=%s", scheme, host, path, args, authKey));
//            return String.format("%s%s%s%s&auth_key=%s", scheme, host, path, args, authKey);
        }
        return map;
    }

    //md5
    private static String md5Sum(String src) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        md5.update(StandardCharsets.UTF_8.encode(src));
        return String.format("%032x", new BigInteger(1, md5.digest()));
    }

    /**
     * 将同步用户信息至云产品平台，若已存在则更新，否则为新增
     */
    public static void createUser(String userId, String userName) {
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", Consts.MyConsts.AliAccessKey, Consts.MyConsts.AliAccessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        //组装请求对象
        CreateUserRequest createUserRequest = new CreateUserRequest();
        //云视频API服务产品域名（接口地址固定，无需修改）
//        createUserRequest.setEncoding("aliyuncvc.cn-hangzhou.aliyuncs.com");
        //设置请求参数
        List<UserInfo> list = new ArrayList();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(userId);
        userInfo.setUserName(userName);
        userInfo.setGroupId("蒲县");
        userInfo.setGroupName("蒲县");
        list.add(userInfo);
        String str = JSONObject.toJSONString(list);
        createUserRequest.setUserInfo(str);
        createUserRequest.setCount(1);
        //获取请求结果
        CreateUserResponse createUserResponse = null;
        try {
            createUserResponse = client.getAcsResponse(createUserRequest);
            if (createUserResponse.getSuccess()) {
                // 业务逻辑

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建会议
     */
    public static CreateMeetingResponse createMeeting(String userId, String meetingName, String pwd, boolean flag) {
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", Consts.MyConsts.AliAccessKey, Consts.MyConsts.AliAccessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        //组装请求对象
        CreateMeetingRequest createMeetingRequest = new CreateMeetingRequest();
        //用户id
        createMeetingRequest.setUserId(userId);
        //会议名称
        createMeetingRequest.setMeetingName(meetingName);
        //会议密码
        createMeetingRequest.setPassword(pwd);
        //是否需要密码
        createMeetingRequest.setOpenPasswordFlag(flag);
        CreateMeetingResponse acsResponse = new CreateMeetingResponse();
        try {
            acsResponse = client.getAcsResponse(createMeetingRequest);
            if (acsResponse.getSuccess()) {
                // 业务逻辑
                System.out.println(JSONObject.toJSONString(acsResponse));
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return acsResponse;
    }

    public static JoinMeetingResponse joinMeeting(String code, String userId, String pwd) {
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", Consts.MyConsts.AliAccessKey, Consts.MyConsts.AliAccessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        //组装请求对象
        JoinMeetingRequest joinMeetingRequest = new JoinMeetingRequest();
        joinMeetingRequest.setMeetingCode(code);
        joinMeetingRequest.setUserId(userId);
        joinMeetingRequest.setPassword(pwd);
        JoinMeetingResponse acsResponse = new JoinMeetingResponse();
        try {
            acsResponse = client.getAcsResponse(joinMeetingRequest);
            if (acsResponse.getErrorCode() == 404) {
                throw new BizException("未找到对应会议");
            }
            if (acsResponse.getErrorCode() == 20042) {
                throw new BizException("会议密码错误");
            }
            System.out.println(JSONObject.toJSONString(acsResponse));
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return acsResponse;
    }

    public static DeleteMeetingResponse deleteMeeting(String uuid) {
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", Consts.MyConsts.AliAccessKey, Consts.MyConsts.AliAccessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        DeleteMeetingRequest deleteMeetingRequest = new DeleteMeetingRequest();
        deleteMeetingRequest.setMeetingUUID(uuid);
        DeleteMeetingResponse acsResponse = new DeleteMeetingResponse();
        try {
            acsResponse = client.getAcsResponse(deleteMeetingRequest);
            if (!acsResponse.getSuccess()) {
                throw new BizException("未知错误");
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return acsResponse;
    }
}
